home *** CD-ROM | disk | FTP | other *** search
-
- #include <string.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <math.h>
-
- #include <OSUtils.h>
- #include <QuickDraw.h>
- #include <Sound.h>
-
- #define NEED_MAC_STUFF 1
-
- #include "Ninkasi:C++ util:generic.h"
- #include "Ninkasi:C++ util:complete_window.h"
- #include "ear_defines.h"
- #include "ear_decl.h"
- #include "ear_prototypes.h"
-
- DEN_MOTHER_T interval_den_mother;
- void choose_interval(int *note1,int *note2,
- int *duration1,int *duration2,int *rest_between,
- int *abs_i,int *lower_note,int *higher_note,
- int max_interval,int *interval_enabled,
- int mean_note,double typical_tempo,int *shorter_duration);
-
-
- void
- interval_den_mother(complete_window *my_complete_window)
- {
- //--- decoder string for controls:
- static char **decoder_string;
- static int have_decoder_string = 0;
- //--- their score:
- static int ntries = 0;
- static int nright = 0;
- static int nright_list[MAX_INTERVAL+1],nwrong_list[MAX_INTERVAL+1];
- //--- keeping track of my current state:
- static int first_time = 1;
- static int they_have_interval_to_consider = 0;
- static int melodic_or_harmonic = 1;
- static int play_it,give_hint,type_of_hint,answer,they_did_something;
- static int they_gave_answer,twiddle_radio_buttons,need_to_redraw,
- twiddle_check_boxes,need_to_redraw_all,ready_to_update,
- right,cleared_scores,changed_tempo;
- static int current_icon = BLANK_ICON_ID;
- //--- parameters that determine what intervals I play and how I play them:
- #define TYPICAL_TEMPO_MELODIC 105
- #define TYPICAL_TEMPO_HARMONIC 45
- static double typical_tempo = TYPICAL_TEMPO_MELODIC;
- static int mean_note = 66;
- static int interval_enabled[MAX_INTERVAL+1];
- //--- about the current interval:
- static int note1,note2,duration1,duration2,rest_between,abs_i,
- shorter_duration;
- static int lower_note = -999;
- static int higher_note = -999;
-
- char nifty_name[100];
- int nifty_index,recognized;
- GrafPtr save_graf;
-
- they_did_something = 0;
- give_hint = 0;
- play_it = 0;
- they_gave_answer = 0;
- twiddle_radio_buttons = 0;
- twiddle_check_boxes = 0;
- need_to_redraw = 0;
- need_to_redraw_all = 0;
- ready_to_update = 0;
- cleared_scores = 0;
- changed_tempo = 0;
-
- if (first_time) {
- first_time = 0;
- for (int i=0; i<=MAX_INTERVAL; i++) {
- nright_list[i] = 0;
- nwrong_list[i] = 0;
- interval_enabled[i] = (i!=0) && (i<=12);
- }
- }
-
- if (!have_decoder_string) {
- decoder_string = (char **) GetString((short) INTERVAL_DLOG_ID);
- if (!VALID_HANDLE(decoder_string))
- bail_out("unable to get decoder string");
- HLock((char **) decoder_string);
- have_decoder_string = 1;
- }
- switch(my_complete_window->whassup) {
- case complete_window_created:
- need_to_redraw = 1;
- need_to_redraw_all = 1;
- break;
- case complete_window_redraw:
- need_to_redraw = 1;
- need_to_redraw_all = 1;
- ready_to_update = 1; //-- main program does begin update & sets graf port
- break;
- case complete_window_action:
- part_number_to_nifty_label(nifty_name,&nifty_index,
- *decoder_string,my_complete_window->part_number);
- if (nifty_index != -999) {
- recognized = 0;
- if (strcmp(nifty_name,"answers")==0) {
- recognized = 1;
- they_gave_answer = 1;
- need_to_redraw = 1;
- answer = nifty_index;
- }
- if (strcmp(nifty_name,"enabled")==0) {
- twiddle_check_boxes = 1;
- need_to_redraw = 1;
- if (nifty_index>=0 && nifty_index<=MAX_INTERVAL)
- interval_enabled[nifty_index] = !interval_enabled[nifty_index];
- recognized = 1;
- }
- if (strcmp(nifty_name,"play_again")==0) {
- recognized = 1;
- play_it = 1;
- }
- if (strcmp(nifty_name,"fifth")==0) {
- recognized = 1;
- give_hint = 1;
- type_of_hint = 6;
- }
- if (strcmp(nifty_name,"octave")==0) {
- recognized = 1;
- give_hint = 1;
- type_of_hint = 1;
- }
- if (strcmp(nifty_name,"connecting_scale")==0) {
- recognized = 1;
- give_hint = 1;
- type_of_hint = 2;
- }
- if (strcmp(nifty_name,"play_lower")==0) {
- recognized = 1;
- give_hint = 1;
- type_of_hint = 3;
- }
- if (strcmp(nifty_name,"compare_with_another")==0) {
- recognized = 1;
- give_hint = 1;
- type_of_hint = 4;
- }
- if (strcmp(nifty_name,"inv")==0) {
- recognized = 1;
- give_hint = 1;
- type_of_hint = 5;
- }
- if (strcmp(nifty_name,"tempol")==0) {
- int bump;
- bump = typical_tempo*.05;
- if (bump<1) bump = 1;
- typical_tempo -= bump;
- if (typical_tempo<10) typical_tempo=10;
- changed_tempo = 1;
- need_to_redraw = 1;
- }
- if (strcmp(nifty_name,"tempoh")==0) {
- int bump;
- bump = typical_tempo*.05;
- if (bump<1) bump = 1;
- typical_tempo += bump;
- if (typical_tempo>300) typical_tempo=300;
- changed_tempo = 1;
- need_to_redraw = 1;
- }
- if (strcmp(nifty_name,"clear_scores")==0) {
- recognized = 1;
- ntries = 0;
- nright = 0;
- {
- int i;
- for (i=0; i<=MAX_INTERVAL; i++) {
- nright_list[i] = 0;
- nwrong_list[i] = 0;
- }
- }
- need_to_redraw = 1;
- cleared_scores = 1;
- current_icon = BLANK_ICON_ID;
- }
- if (strcmp(nifty_name,"melodic")==0) {
- melodic_or_harmonic = 1;
- twiddle_radio_buttons = 1;
- need_to_redraw = 1;
- typical_tempo = TYPICAL_TEMPO_MELODIC;
- recognized = 1;
- }
- if (strcmp(nifty_name,"harmonic")==0) {
- melodic_or_harmonic = 2;
- twiddle_radio_buttons = 1;
- need_to_redraw = 1;
- typical_tempo = TYPICAL_TEMPO_HARMONIC;
- recognized = 1;
- }
- they_did_something = recognized;
- }//--end if they hit a valid control
- break;
- case complete_window_erase:
- they_have_interval_to_consider = 0;
- first_time = 1;
- interval_window_exists = 0;
- return;
- }
-
-
- if (they_gave_answer) {
- right = (answer == abs_i);
- ++ntries;
- nright += right;
- if (right) {
- current_icon = CHECK_ICON_ID;
- ++nright_list[abs_i];
- }
- else {
- current_icon = X_ICON_ID;
- ++nwrong_list[abs_i];
- }
- they_have_interval_to_consider = 0;
- }
- if (need_to_redraw) {
- if (!ready_to_update) {
- GetPort(&save_graf);
- SetPort(my_complete_window->the_window);
- }
- if (twiddle_radio_buttons || need_to_redraw_all) {
- set_ctl_by_nifty_label(my_complete_window->the_window,
- "melodic",1,*decoder_string,(melodic_or_harmonic==1));
- set_ctl_by_nifty_label(my_complete_window->the_window,
- "harmonic",1,*decoder_string,(melodic_or_harmonic==2));
- }
- if (twiddle_check_boxes || need_to_redraw_all) {
- for (int i=0; i<=MAX_INTERVAL; i++) {
- set_ctl_by_nifty_label(my_complete_window->the_window,
- "enabled",i,*decoder_string,interval_enabled[i]);
- }
- }
- if (need_to_redraw_all) {
- refresh_text(my_complete_window,"tx",1,*decoder_string);
- }
- if (changed_tempo || twiddle_radio_buttons || need_to_redraw_all) {
- Handle h;
- char s[50];
- get_item_by_nifty_label(my_complete_window->the_window,
- "tempo",1,*decoder_string,&h);
- if (VALID_HANDLE(h)) {
- sprintf(s+1,"%d",(int) typical_tempo);
- s[0] = strlen(s+1);
- SetIText(h,(unsigned char *) s);
- }
- }
- if (they_gave_answer || cleared_scores || need_to_redraw_all) {
- Handle h;
- char s[50];
- int i,tot;
- get_item_by_nifty_label(my_complete_window->the_window,
- "total_score",1,*decoder_string,&h);
- if (VALID_HANDLE(h)) {
- if (ntries>0) {
- sprintf(s+1,"%d %c",(int) ((100.*nright)/((double) ntries)),'%');
- s[0] = strlen(s+1);
- }
- else {
- sprintf(s+1," ");
- s[0] = strlen(s+1);
- }
- TextSize((short) 18);
- TextFont(geneva);
- SetIText(h,(unsigned char *) s);
- normal_text_style();
- }
- get_item_by_nifty_label(my_complete_window->the_window,
- "totals",1,*decoder_string,&h);
- if (VALID_HANDLE(h)) {
- if (ntries>0) {
- sprintf(s+1,"%d / %d",(int) nright,(int) ntries);
- s[0] = strlen(s+1);
- }
- else {
- sprintf(s+1," ");
- s[0] = strlen(s+1);
- }
- TextFont(geneva);
- SetIText(h,(unsigned char *) s);
- normal_text_style();
- }
-
- TextFont((short) geneva);
- for (i=0; i<=MAX_INTERVAL; i++) {
- tot = nright_list[i]+nwrong_list[i];
- if (need_to_redraw_all || cleared_scores
- || (they_gave_answer && i==abs_i)) {
- get_item_by_nifty_label(my_complete_window->the_window,
- "scores",i,*decoder_string,&h);
- if (VALID_HANDLE(h)) {
- if (tot>0) {
- sprintf(s+1,"%d / %d",(int) nright_list[i],(int) tot);
- s[0] = strlen(s+1);
- }
- else {
- sprintf(s+1," ");
- s[0] = strlen(s+1);
- }
- SetIText(h,(unsigned char *) s);
- }
- }
- }//-- end loop over intervals
- normal_text_style();
- }
- if (they_gave_answer) {
- int i;
- if (!right) {
- for (i=0; i<=MAX_INTERVAL; i++) {
- if (i!=abs_i)
- hide_ctl_by_nifty_label(my_complete_window->the_window,
- "answers",i,*decoder_string);
- }
- }
- }
- if (they_gave_answer || cleared_scores || need_to_redraw_all) {
- Handle hh;
- Rect rr;
- hh = GetIcon((short) current_icon);
- if (VALID_HANDLE(hh)) {
- get_rect_by_nifty_label(my_complete_window->the_window,
- "icon",1,*decoder_string, &rr);
- PlotIcon(&rr,hh);
- }
- }
- if (they_gave_answer && !right) {
- int i;
- rest((int)( 2. * 2000.*60./typical_tempo));
- for (i=0; i<=MAX_INTERVAL; i++) {
- if (i!=abs_i)
- show_ctl_by_nifty_label(my_complete_window->the_window,
- "answers",i,*decoder_string);
- }
- }
- if (!ready_to_update) {
- SetPort(save_graf);
- }
- }//---end if need to redraw
- if (!they_have_interval_to_consider) {
- int previous_lower,previous_higher;
- previous_lower = lower_note;
- previous_higher = higher_note;
- do {
- choose_interval(¬e1,¬e2,&duration1,&duration2,&rest_between,
- &abs_i,&lower_note,&higher_note,
- MAX_INTERVAL,interval_enabled,
- mean_note,typical_tempo,&shorter_duration);
- } while (previous_lower==lower_note && previous_higher==higher_note);
- play_it = 1;
- they_have_interval_to_consider = 1;
- }
- if (play_it) {
- int notes[4];
- switch(melodic_or_harmonic) {
- case 1: //-- melodic
- notes[0] = note1;
- play_chord(1,my_snd_chan,notes,duration1,1);
- rest(rest_between);
- notes[0] = note2;
- play_chord(1,my_snd_chan,notes,duration2,1);
- break;
- case 2:
- notes[0] = note1;
- notes[1] = note2;
- play_chord(2,my_snd_chan,notes,duration1,1);
- break;
- }
- }
- if (give_hint) {
- int notes[4];
- switch(type_of_hint) {
- case 1: //-- play octave
- notes[0] = lower_note;
- play_chord(1,my_snd_chan,notes,shorter_duration,1);
- notes[0] = lower_note+12;
- play_chord(1,my_snd_chan,notes,shorter_duration,1);
- break;
- case 2: //-- play connecting scale
- {
- int *what_scale;
- int i;
- what_scale = interval_is_in_major_scale;
- if ( !interval_is_in_major_scale[make_0_to_11(abs_i)]
- && interval_is_in_minor_scale[make_0_to_11(abs_i)])
- what_scale = interval_is_in_minor_scale;
- for (i=0; i<=abs_i; i++) {
- if (what_scale[make_0_to_11(i)] || i==abs_i) {
- notes[0] = lower_note+i;
- play_chord(1,my_snd_chan,notes,shorter_duration/2,1);
- }
- }
- }
- break;
- case 3: //-- play the lower note
- notes[0] = lower_note;
- play_chord(1,my_snd_chan,notes,duration1,1);
- break;
- case 4: //-- compare with another interval
- {
- DialogPtr my_dialog;
- short item_hit;
- int interval;
- my_dialog = GetNewDialog(SELECT_INTERVAL_MODAL_DLOG_ID,
- 0,(WindowPtr) -1);
- if (VALID_POINTER(my_dialog)) {
- ModalDialog(0,&item_hit);
- DisposDialog(my_dialog);
- interval = item_hit - 1;
- if (interval>=0 && interval<=MAX_INTERVAL) {
- notes[0] = lower_note;
- play_chord(1,my_snd_chan,notes,shorter_duration,1);
- notes[0] = lower_note+interval;
- play_chord(1,my_snd_chan,notes,shorter_duration,1);
- }
- }
- }
- break;
- case 5: //-- play inversion
- notes[0] = note1;
- if (notes[0]==lower_note) notes[0]+=12;
- play_chord(1,my_snd_chan,notes,duration1,1);
- notes[0] = note2;
- if (notes[0]==lower_note) notes[0]+=12;
- play_chord(1,my_snd_chan,notes,duration1,1);
- break;
- case 6: //-- play fifth
- notes[0] = lower_note;
- play_chord(1,my_snd_chan,notes,shorter_duration,1);
- notes[0] = lower_note+7;
- play_chord(1,my_snd_chan,notes,shorter_duration,1);
- break;
- }
- }
-
- }
-
-
- void
- choose_interval(int *note1,int *note2,int *duration1,int *duration2,int *rest_between,
- int *abs_i,int *lower_note,int *higher_note,
- int max_interval,int *interval_enabled,
- int mean_note,double typical_tempo,int *shorter_duration)
- {
- int interval,center,interval1,interval2,min_duration,
- max_duration,temp;
- double tempo,r1,r2,r3;
- do {
- interval1 = random_double()*max_interval*1.6;
- interval2 = random_double()*max_interval*1.6;
- if (interval1<interval2)
- interval=interval1;
- else
- interval=interval2;
- while ( random_double()<.5
- && random_double()*max_interval*.3>interval)
- ++interval;
- }while(interval<0 || interval>max_interval || !interval_enabled[interval]);
- center = mean_note+(random_double()-.5)*8+(random_double()-.5)*8;
- /* mean_note plus or minus an something, biased towards
- pitches close to mean_note */
- *abs_i = interval;
- if (random_double()<.5) interval = -interval;
- *note1 = center-interval/2;
- *note2 = *note1 + interval;
-
- min_duration = .7 * 2000.*60./typical_tempo;
- max_duration = 4 * 2000.*60./typical_tempo;
- do {
- tempo = typical_tempo*(1.+.2*(random_double()+random_double()-1.));
- *duration1 = 2000.*60./tempo;
- *duration2 = (*duration1)*small_integer_ratio();
- if (random_double()<.5) {
- temp = *duration1;
- *duration1 = *duration2;
- *duration2 = temp;
- }
- while (*duration1<min_duration || *duration2<min_duration) {
- (*duration1) *= 2;
- (*duration2) *= 2;
- }
- while (*duration1>max_duration || *duration2>max_duration) {
- (*duration1) /= 2;
- (*duration2) /= 2;
- }
- } while (*duration1>max_duration || *duration2>max_duration
- || *duration1<min_duration || *duration2<min_duration);
- *shorter_duration = (*duration1)/2;
- while (*shorter_duration<min_duration) {
- (*shorter_duration) *= 2;
- }
- while (*shorter_duration>min_duration*2) {
- (*shorter_duration) /= 2;
- }
- r1 = random_double();
- r2 = random_double();
- r3 = random_double();
- if (r1<.5) {
- if (r2<.33)
- *rest_between = *duration1;
- else {
- if (r2<.66)
- *rest_between = *duration2;
- else {
- if (r3<.5)
- *rest_between = (*duration1) * small_integer_ratio();
- else
- *rest_between = (*duration2) * small_integer_ratio();
- }
- }
- }
- else
- *rest_between = 0;
-
- ++ *rest_between; /* always make it slightly staccato */
- -- *duration1; /* take the time out of the first note */
- if (*note1<*note2) {
- *lower_note = *note1;
- *higher_note = *note2;
- }
- else {
- *lower_note = *note2;
- *higher_note = *note1;
- }
- }
-
-